/*
 * Copyright (c) 2018-2999 广州亚米信息科技有限公司 All rights reserved.
 *
 * https://www.gz-yami.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

package com.yami.shop.discount.api.manager.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.BooleanUtil;
import com.google.common.collect.Lists;
import com.yami.shop.bean.app.dto.ChooseDiscountItemDto;
import com.yami.shop.bean.app.dto.ShopCartDto;
import com.yami.shop.bean.app.dto.ShopCartItemDiscountDto;
import com.yami.shop.bean.app.dto.ShopCartItemDto;
import com.yami.shop.bean.enums.OrderActivityType;
import com.yami.shop.bean.vo.ShopCartWithAmountVO;
import com.yami.shop.common.util.Arith;
import com.yami.shop.discount.api.dto.DiscountSumDto;
import com.yami.shop.discount.api.service.DiscountManagerService;
import com.yami.shop.manager.DiscountShopCartManager;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 默认的购物车链进行组装时的操作
 *
 * @author FrozenWatermelon
 */
@Component
@AllArgsConstructor
public class DiscountShopCartManagerImpl implements DiscountShopCartManager {

    private final DiscountManagerService discountManagerService;

    /**
     * 计算满减，并组合购物车 + 购物车金额
     *
     * @param shopCartWithAmount 购物车列表和金额信息
     */
    @Override
    public void calculateDiscountAndMakeUpShopCartAndAmount(ShopCartWithAmountVO shopCartWithAmount) {
        List<ShopCartDto> shopCarts = shopCartWithAmount.getShopCarts();
        shopCarts = calculateDiscountAndMakeUpShopCart(shopCarts);
        shopCartWithAmount.setShopCarts(shopCarts);
    }

    /**
     * 计算满减，并重新组合购物车
     * @param shopCarts 购物项
     * @return void
     */
    @Override
    public List<ShopCartDto> calculateDiscountAndMakeUpShopCart(List<ShopCartDto> shopCarts) {
        List<ShopCartDto> newShopCart = new ArrayList<>();
        for (ShopCartDto shopCart : shopCarts) {
            List<ShopCartItemDto> canDiscountShopCartItems = shopCart.getShopCartItemDiscounts()
                    .get(0).getShopCartItems().stream().filter(shopCartItemDto ->
                        // 套餐不参与满减
                        (Objects.isNull(shopCartItemDto.getComboId()) || shopCartItemDto.getComboId() == 0)
//                        // 预售不参与满减
//                        && (Objects.isNull(shopCartItemDto.getPreSellStatus()) || Objects.equals(shopCartItemDto.getPreSellStatus(), 0))
                    )
                    .collect(Collectors.toList());
            if (CollUtil.isEmpty(canDiscountShopCartItems)) {
                newShopCart.add(shopCart);
            } else {
                newShopCart.add(reBuildShopCart(shopCart, canDiscountShopCartItems));
            }
        }
        return newShopCart;
    }

    /**
     * 重新组装购物车
     */
    private ShopCartDto reBuildShopCart(ShopCartDto shopCart, List<ShopCartItemDto> shopCartItems) {
        // 购物车项顺序
        List<Long> cartOrderArr = shopCartItems.stream().map(ShopCartItemDto::getBasketId).collect(Collectors.toList());
        // 订单项金额从小到大排序
        shopCartItems = shopCartItems.stream().sorted(Comparator.comparingDouble(ShopCartItemDto::getActualTotal)).collect(Collectors.toList());

        shopCart.setShopReduce(0.0);
        shopCart.setDiscountReduce(0.0);
        // 1.获取总的优惠金额
        // 2.将商品活动进行保存
        DiscountSumDto discountSum = discountManagerService.calculateDiscount(shopCart.getShopId(), shopCartItems);

        List<ShopCartItemDiscountDto> shopCartItemDiscountVOList = Lists.newArrayList();

        // 对数据进行组装
        // 通过活动项id划分,获取有活动的商品项
        Map<Long, List<ShopCartItemDto>> hasDiscountShopCartItemMap = shopCartItems.stream().collect(Collectors.groupingBy(ShopCartItemDto::getDiscountId));

        double reduce = 0.0;
        double total = 0.0;
        int totalCount = 0;
        for (Long discountId : hasDiscountShopCartItemMap.keySet()) {
            // 获取该列表
            List<ShopCartItemDto> shopCartItemList = hasDiscountShopCartItemMap.get(discountId);
            ChooseDiscountItemDto chooseDiscountItemDto = discountManagerService.getChooseDiscountItemDto(discountSum, discountId);
            double discountAmount = 0.0;

            // 分摊优惠大于订单项金额的数量
            double shareReduceBiggerThenShopItemAmount = 0;
            // 计算分摊优惠金额
            for (int index = 0; index < shopCartItemList.size(); index++) {

                ShopCartItemDto shopCartItem = shopCartItemList.get(index);
                total = Arith.add(total, shopCartItem.getProductTotalAmount());
                totalCount += shopCartItem.getProdCount();

                if (!BooleanUtil.isTrue(shopCartItem.getIsChecked()) && Objects.nonNull(shopCartItem.getIsChecked())) {
                    continue;
                }

                double shareReduce = 0.0;
                if (Objects.isNull(chooseDiscountItemDto)) {
                    shopCartItem.setShareReduce(shareReduce);
                    shopCartItem.setActualTotal(shopCartItem.getActualTotal() - shareReduce);
                    continue;
                }
                double reduceAmount = Arith.roundByBanker(chooseDiscountItemDto.getReduceAmount(),2);
                if (index + 1 == shopCartItems.size()) {
                    shareReduce = reduceAmount - discountAmount;
                    // 如果分到最后一项的钱太多了，比订单项目金额都要多，订单项的分摊金额就当作订单项金额咯
                    if (shareReduce > shopCartItem.getActualTotal()) {
                        shareReduceBiggerThenShopItemAmount = Arith.sub(shareReduce, shopCartItem.getActualTotal());
                        shareReduce = shopCartItem.getActualTotal();
                        // 给得太多了，减少一点，以免变成负数
                        chooseDiscountItemDto.setReduceAmount(Arith.sub(reduceAmount, shareReduceBiggerThenShopItemAmount));
                    }
                } else {
                    // 分摊金额 = 该优惠活动优惠金额 * (商品金额 / 参与该活动的商品总金额)
                    shareReduce = Arith.roundByBanker(Arith.mul(chooseDiscountItemDto.getReduceAmount(), Arith.div(shopCartItem.getProductTotalAmount(),
                            chooseDiscountItemDto.getProdsPrice())),2);
                }
                // 第一个优惠就是满减
                shopCartItem.setShareReduce(shareReduce);
                shopCartItem.setDiscountAmount(shareReduce);
                shopCartItem.setActualTotal(Arith.sub(shopCartItem.getActualTotal(), shareReduce));
                discountAmount = Arith.add(discountAmount, shareReduce);
            }
            ShopCartItemDiscountDto shopCartItemDiscount = new ShopCartItemDiscountDto();
            // 不要把这行放到上面，因为上面会重新计算该值
            if (chooseDiscountItemDto != null) {
                reduce = Arith.add(reduce, Arith.roundByBanker(chooseDiscountItemDto.getReduceAmount(),2));
                shopCartItemDiscount.setActivityType(OrderActivityType.DISCOUNT.value());
            }
            // 把购物车项的商品顺序还原
            shopCartItemList.sort(Comparator.comparingInt(prev -> cartOrderArr.indexOf(prev.getBasketId())));

            shopCartItemDiscount.setShopCartItems(shopCartItemList);
            shopCartItemDiscount.setChooseDiscountItemDto(chooseDiscountItemDto);
            shopCartItemDiscountVOList.add(shopCartItemDiscount);
        }
        // 倒序排序，将拥有优惠活动的商品放到最上面
        Collections.reverse(shopCartItemDiscountVOList);
        // 除满减外其他活动的商品构建
        buildOtherShopCartItem(shopCart, shopCartItemDiscountVOList);

        shopCart.setShopCartItemDiscounts(shopCartItemDiscountVOList);
        shopCart.setTotal(total);
        shopCart.setTotalCount(totalCount);
        shopCart.setActualTotal(Arith.sub(total, reduce));
        shopCart.setDiscountReduce(reduce);
        // 最开始的店铺满减
        shopCart.setShopReduce(reduce);
        return shopCart;
    }

    private void buildOtherShopCartItem(ShopCartDto shopCart, List<ShopCartItemDiscountDto> shopCartItemDiscountVOList) {
        List<ShopCartItemDto> comboShopCartItemList = shopCart.getShopCartItemDiscounts().get(0).getShopCartItems().stream().filter(shopCartItemDto ->
                (Objects.nonNull(shopCartItemDto.getComboId()) && shopCartItemDto.getComboId() != 0)).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(comboShopCartItemList)) {
            shopCartItemDiscountVOList.add(new ShopCartItemDiscountDto(comboShopCartItemList));
        }
//        List<ShopCartItemDto> preSellShopCartItemList = shopCart.getShopCartItemDiscounts().get(0).getShopCartItems().stream().filter(shopCartItemDto ->
//                (Objects.nonNull(shopCartItemDto.getPreSellStatus()) && Objects.equals(shopCartItemDto.getPreSellStatus(), 1))).collect(Collectors.toList());
//        if (CollUtil.isNotEmpty(preSellShopCartItemList)) {
//            shopCartItemDiscountVOList.add(new ShopCartItemDiscountDto(preSellShopCartItemList));
//        }
    }
}
